//
//  PhotoLibraryManager.swift
//  ltsp
//
//  Created by jyvyi_ios on 2022/6/15.
//

import Foundation

/*
 <key>NSPhotoLibraryUsageDescription</key>
 <string>App需要您的同意,才能访问相册</string>
 */

protocol PhotoLibraryManager_Read_h{
    
    /// 获取相册中的视频
    /// - Parameter completeBlock: ～
    static func loadLibraryDataOfVideo(completeBlock:@escaping (PhotoVideoModel)->())
    
    // 获取相簿
    static func fetchAssetCollections(with options:PHFetchOptions?) -> PHFetchResult<PHAssetCollection>
    
    //获取相簿下的文件
    static func fetchAssets(in assetCollection:PHAssetCollection, options:PHFetchOptions?) -> PHFetchResult<PHAsset>
    
    //读取文件信息
    static func readInfo(of asset:PHAsset,completeBlock:@escaping (AVURLAsset?)->())
}
protocol PhotoLibraryManager_Write_h{
    
    /// 保存应用内的视频到相册
    /// - Parameters:
    ///   - url: 应用内的路径
    ///   - successBlock: 成功回调
    ///   - failureBlock: 失败回调
    func saveToLibrary(at url:URL,successBlock:@escaping ReturnValueBlock<String>,failureBlock:ReturnValueBlock<String>?)
}
class PhotoLibraryManager : NSObject{
    
    fileprivate var saveSuccessBlock: ReturnValueBlock<String>?
    
    fileprivate var saveFailureBlock: ReturnValueBlock<String>?
    
    //文件筛选条件
    fileprivate static var fetchAlbumOptions: PHFetchOptions = {
        
        let options = PHFetchOptions()
        let timeSort = NSSortDescriptor.init(key: "creationDate", ascending: false)
        options.sortDescriptors = [timeSort]  //时间排序
        let type : PHAssetMediaType = .video  //设置筛选视频
        options.predicate = NSPredicate.init(format: "mediaType == %ld", type.rawValue)
        options.fetchLimit = 50
        options.includeAssetSourceTypes = .typeUserLibrary
        return options
    }()
}
extension PhotoLibraryManager : PhotoLibraryManager_Write_h{
    
    func saveToLibrary(at url:URL,successBlock:@escaping ReturnValueBlock<String>,failureBlock:ReturnValueBlock<String>? = nil){
        
        guard UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(url.absoluteString) else {
            failureBlock?("该视频无法保存至相册")
            return
        }
        self.saveSuccessBlock = successBlock
        self.saveFailureBlock = failureBlock
        UISaveVideoAtPathToSavedPhotosAlbum(url.path, self, #selector(didFinishSavingVideo(videoPath:error:contextInfo:)), nil)
    }
    
    @objc func didFinishSavingVideo(videoPath: String, error: NSError?, contextInfo: UnsafeMutableRawPointer?) {
        
        if error != nil{
            debugPrint(error!)
            self.saveFailureBlock?("保存失败")
        }else{
            self.saveSuccessBlock?("保存成功，请到相册中查看")
        }
    }
}
extension PhotoLibraryManager : PhotoLibraryManager_Read_h{
    
    static func loadLibraryDataOfVideo(completeBlock:@escaping (PhotoVideoModel)->()) {
        
        if AuthorizationManager.isPhotoLibraryAllowed(){
            
            self.requestLibraryOfVideo(completeBlock: completeBlock)
        }
        else{
            AuthorizationManager.requestPhotoLibraryAuthorization { status in
                
                self.requestLibraryOfVideo(completeBlock: completeBlock)
            }
        }
    }
    
    static func fetchAssetCollections(with options:PHFetchOptions? = nil) -> PHFetchResult<PHAssetCollection>{
         
         let collectionType : PHAssetCollectionType = .smartAlbum
        let collectionSubType : PHAssetCollectionSubtype = .smartAlbumUserLibrary  //获取所有
         let assetCollections : PHFetchResult<PHAssetCollection> = PHAssetCollection.fetchAssetCollections(with: collectionType, subtype: collectionSubType, options: options)
         return assetCollections
     }

     static func fetchAssets(in assetCollection:PHAssetCollection, options:PHFetchOptions? = nil) -> PHFetchResult<PHAsset>{

         let albumAssets : PHFetchResult<PHAsset> = PHAsset.fetchAssets(in: assetCollection, options: options)
         return albumAssets
     }

     static func readInfo(of asset:PHAsset,completeBlock:@escaping (AVURLAsset?)->()){
         let options = PHVideoRequestOptions()
         options.version = .current
         options.deliveryMode = .automatic
         PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { avAsset, audioMix, info in
             
             let avAsset1 : AVURLAsset? = avAsset as? AVURLAsset
             completeBlock(avAsset1)
         }
     }
}
extension PhotoLibraryManager : URLSessionDelegate{
    
}
extension PhotoLibraryManager{

    fileprivate static func requestLibraryOfVideo(completeBlock:@escaping (PhotoVideoModel)->()){
       
        DispatchQueue.global().async {
            
            self.fetchAssetCollections().enumerateObjects { assetCollection, count, unUsed in
                
                self.fetchAssets(in: assetCollection, options: self.fetchAlbumOptions).enumerateObjects { asset, count, unUsed in
                    
                    self.readInfo(of: asset) { avUrlAsset in
                        
                        if let avUrlAsset = avUrlAsset{
                            let model = PhotoVideoModel.init(with: avUrlAsset)
                            DispatchQueue.main.async {
                                completeBlock(model)
                            }
                        }
                    }
                }
            }
        }
    }
}
class PhotoVideoModel : Equatable{
    
    static func == (lhs: PhotoVideoModel, rhs: PhotoVideoModel) -> Bool {
        
        return lhs.url?.absoluteString == rhs.url?.absoluteString
    }
    
    var time : String?  //视频时长
    var videoImage : UIImage?  //视频图片
    var url : URL?  //视频路径
    var cover : UIImage?  //封面
    
    init(with asset:AVURLAsset){
        
        self.time = asset.duration.transformVideoTimeToString()
        self.videoImage = UIImage.image(of: asset)
        self.cover = self.videoImage
        self.url = asset.url
    }
}
